using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using Instedd.Labs.Geo.Library.Rss;
using Instedd.Labs.Geo.Library.Kml;

namespace Instedd.Labs.GeoBlogging.WebApplication
{
    public partial class GetFeed : System.Web.UI.Page
    {
        const int MAX_COMMENTS_TO_SHOW_IN_PUSHPIN = 4;
        protected void Page_Load(object sender, EventArgs e)
        {
            String feedType = Request.QueryString["t"];
            // if type not specified, assume GeoRSS
            if (String.IsNullOrEmpty(feedType))
            {
                feedType = "georss";
            }
            feedType = feedType.ToLower();

            if (feedType == "georss")
            {
                if (Request.QueryString["c"] != null && Request.QueryString["c"].ToLower() == "ve")
                {
                    GenerateGeoRssFeed(false,true);
                }
                else
                {
                    GenerateGeoRssFeed(true,false);
                }
            }
            else if (feedType == "kml")
            {
                if (Request.QueryString["c"] != null && Request.QueryString["c"].ToLower() == "ge")
                {
                    // render the KML as an attachment so the user is asked to open/save the file and the locally
                    // installed GE has a chance at opening it.
                    GenerateKmlFeed(true);
                }
                {
                    GenerateKmlFeed(false);
                }
            }
            // an invalid/unsupported feed type has been specified
            else
            {
                return;
            }
        }

        void GenerateGeoRssFeed(bool useGeoRss, bool useGeo)
        {
            Response.Clear();
            //Response.AppendHeader("Content-Disposition", "filename=feed.xml");
            Response.Buffer = false;
            Response.ContentType = "application/xml";
            Response.ContentEncoding = Encoding.UTF8;

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = Encoding.UTF8;
            XmlWriter writer = XmlWriter.Create(Response.OutputStream, settings);
            writer.Flush();

            List<Item> items = DataAccess.GetAllItems();
            items = DataAccess.GetAllItems();
            items = ProcessItemDescription(items);

            RssFormat feed = new RssFormat();
            Channel channel = new Channel();
            channel.LastBuildDate = DateTime.Now;
            channel.Title = "InSTEDD GeoBlogging";
            channel.PubDate = DateTime.Now;
            channel.Link = "http://goldenshadow.clariusconsulting.net";
            channel.Description = "Posting from around the world";
            channel.Items = items;
            
            feed.Channels.Add(channel);

            RssWriter rssWriter = new RssWriter();
            RssWriterSettings rssSettings = new RssWriterSettings();
            rssSettings.UseGeo = useGeo;
            rssSettings.UseGeoRss = useGeoRss;
            rssWriter.WriteRss(writer, feed, rssSettings);
            writer.Flush();
            Response.End();
        }

        List<Item> ProcessItemDescription(List<Item> items)
        {
            foreach (Item ite in items)
            {
                String newDescription = GetContentForBubble(ite);
                ite.Description = newDescription;
            }

            return items;
        }

        void GenerateKmlFeed(bool renderAsAttachment)
        {
            Response.Clear();
            if (renderAsAttachment)
            {
                Response.AppendHeader("Content-Disposition", "filename=GeoBlogging.kml;attachment");
            }
            Response.Buffer = false;
            Response.ContentType = "application/xml";
            Response.ContentEncoding = Encoding.UTF8;

            StringBuilder sb = new StringBuilder ();

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = Encoding.UTF8;
            XmlWriter writer = XmlWriter.Create(Response.OutputStream, settings);
            writer.Flush();

            List<Item> items = DataAccess.GetAllItems();

            KmlFormat kml = new KmlFormat();
            foreach (Item ite in items)
            {
                String description = GetContentForBubble(ite);
                Placemark placemark = new Placemark(ite.Title, description, ite.LatLong, ite.PubDate);
                Folder folder = GetFolderForCreator(ite.Creator);
                folder.Placemarks.Add(placemark);
            }

            kml.Folders = new List<Folder>(foldersByCreator.Values);

            KmlWriter kmlWriter = new KmlWriter();
            kmlWriter.WriteKml(writer, kml);
            writer.Flush();
            Response.End();
        }

        Dictionary<String, Folder> foldersByCreator = new Dictionary<string, Folder>();

        Folder GetFolderForCreator(String createdBy)
        {
            if (foldersByCreator.ContainsKey(createdBy))
            {
                return foldersByCreator[createdBy];
            }

            Folder folder = new Folder(createdBy);
            foldersByCreator.Add(createdBy, folder);
            return folder;
        }

        String GetHtmlForLastComments(List<Comment> comments)
        {
            if (comments.Count == 0)
            {
                return null; 
            }

            int totalComments = comments.Count > MAX_COMMENTS_TO_SHOW_IN_PUSHPIN ? MAX_COMMENTS_TO_SHOW_IN_PUSHPIN : comments.Count;

            StringBuilder sb = new StringBuilder();
            TimeSpan ts = DateTime.Now - comments[comments.Count - 1].When;

            sb.AppendFormat("Last {0} comments {1} ago:<br/>", totalComments, GetLastTimeAgo(ts));
            for (int c = comments.Count - totalComments; c < comments.Count; c++)
            {
                Comment comment = comments[c];
                sb.AppendFormat(String.Format("from {0}: \"{1}\"<br/>", comment.Name, comment.Description));

            }
            return sb.ToString();
        }

        String GetLastTimeAgo(TimeSpan ts)
        {
            if (ts.Days > 30)
            {
                return String.Format("{0} months", ts.Days/30);
            }
            else if (ts.Days > 0 && ts.Days <= 30)
            {
                return String.Format("{0} days", ts.Days);
            }
            else if (ts.Hours > 0)
            {
                return String.Format("{0} hours", ts.Hours);
            }
            else
            {
                int min = ts.Minutes > 0 ? ts.Minutes : 1;
                return String.Format("{0} minutes", min);
            }
        }

        String GetContentForBubble(Item ite)
        {
            String showPostLink = String.Format("<a href='{0}'>View Post</a>", ite.Link);
            String replyPostLink = String.Format("<a href='{0}#comments'>Reply</a>", ite.Link);
            String viewAllComments = String.Empty;
            String description = String.Empty;
            if (ite.Comments.Count > 0)
            {
                viewAllComments = String.Format("<a href='{0}#comments'>View comments ({1})</a>", ite.Link, ite.Comments.Count);
            }

            if (viewAllComments != null)
            {
                String commentsHtml = GetHtmlForLastComments(ite.Comments);
                description = String.Format("<br/>{0}<br/><br/>{4}<br/><br/>{1} | {2} | {3}", ite.Description, showPostLink, replyPostLink, viewAllComments, commentsHtml);
            }
            else
            {
                description = String.Format("<br/>{0}<br/><br/>{1} | {2}", ite.Description, showPostLink, replyPostLink);
            }

            return description;
        }
    }
}
